package org.kca.yarmour.view;

import static org.lwjgl.opengl.GL11.*;

import org.kca.graphics.GameCore;
import org.kca.yarmour.data.GlobalData.CargoType;
import org.kca.yarmour.utils.ImageUtils;
import org.kca.yarmour.utils.KcaGLUtils;
import org.lwjgl.input.Keyboard;

public class NumberDialog extends PopupDialog
{
    private final static int DIALOG_WIDTH = 200;
    private final static int DIALOG_HEIGHT = 120;
    private final static int BOX_X = 65;
    private final static int BOX_Y = TITLEBAR_HEIGHT + 8;
    private final static int BOX_W = 70;
    private final static int BOX_H = 25;
    private final static int BAR_X = 30;
    private final static int BAR_W = 140;
    private final static int BAR_Y = BOX_Y + BOX_H + 15;
    private final static int SLIDER_R = 5;
    private final static int OK_BUTTON_X = 70;
    private final static int OK_BUTTON_W = 60;
    private final static int OK_BUTTON_Y = BAR_Y + 15;
    private final static int OK_BUTTON_H = 30;
    
    private int curValue, maxValue;
    private StringBuffer sb;
    private int caretPos, maxLen;
    private long lastActTime;
    private int mouseDownX, mouseDownY, sliderPos;
    private boolean sliderDragged;
    
    public NumberDialog(String title, int current, int max)
    {
        super(DIALOG_WIDTH, DIALOG_HEIGHT, title);
        this.curValue = current;
        this.maxValue = max;
        maxLen = String.valueOf(max).length();
        sb = new StringBuffer();
        if (curValue != 0) 
        {
            // start blank if value is 0
            sb.append(curValue);
        }
        caretPos = sb.length();
        lastActTime = GameCore.getTime();
        sliderDragged = false;
    }
    
    @Override
    protected void drawContent()
    {
        String valStr = sb.toString(); 
        int xp = Math.min(BAR_W, Math.round((getValue() * BAR_W) / (float)maxValue));
        if (sliderDragged)
        {
            xp = (sliderPos + getMouseX() - mouseDownX) - BAR_X;
            xp = Math.max(0, Math.min(xp, BAR_W));
            int value = Math.round(xp * maxValue / (float)BAR_W);
            valStr = String.valueOf(value);
            caretPos = valStr.length();
        }
        glColor4f(0, 0, 0, 1);
        KcaGLUtils.drawRect(BOX_X, BOX_Y, BOX_W, BOX_H);
        int nx = ImageUtils.centerAlignX(DIALOG_FONT, BOX_X + BOX_W / 2, valStr);
        DIALOG_FONT.drawString(valStr, nx, BOX_Y + (BOX_H - DIALOG_FONT.getHeight()) / 2);
        if (((GameCore.getTime() - lastActTime) % 1200) / 600 == 0)
        {
            int cx = nx + DIALOG_FONT.stringWidth(valStr.substring(0, caretPos)) + 1;
            KcaGLUtils.drawLine(cx, BOX_Y + 2, cx, BOX_Y + BOX_H - 2);
        }
        // draw scroll bar
        KcaGLUtils.drawLine(BAR_X, BAR_Y, BAR_X + BAR_W, BAR_Y);
        glColor4f(0.2f, 1, 0.2f, 1);
        KcaGLUtils.fillCircle(BAR_X + xp, BAR_Y, SLIDER_R, 24);
        glColor4f(0.1f, 0.6f, 0.1f, 1);
        KcaGLUtils.drawCircle(BAR_X + xp, BAR_Y, SLIDER_R, 24);
        KcaGLUtils.drawButton(OK_BUTTON_X, OK_BUTTON_Y, OK_BUTTON_W, OK_BUTTON_H, TITLEBAR_FONT,
                "Ok", KcaGLUtils.BUTTON_ENABLED);
    }
    
    /**
     * Gets the value entered in this number dialog
     * @return the value
     */
    public int getValue()
    {
        if (sb.length() == 0)
        {
            return 0;
        }
        else
        {
            return Math.min(maxValue, Integer.parseInt(sb.toString()));
        }
    }
    
    /**
     * Moves the caret left by 1 position if possible
     */
    private void moveCaretLeft()
    {
        if (caretPos > 0)
        {
            caretPos--;
            lastActTime = GameCore.getTime();
        }
    }
    
    /**
     * Moves the caret right by 1 position if possible
     */
    private void moveCaretRight()
    {
        if (caretPos < sb.length())
        {
            caretPos++;
            lastActTime = GameCore.getTime();
        }
    }
    
    /**
     * Deletes a char in front or behind the caret
     * @param del set to true to delete in front, false to delete behind
     */
    private void deletePressed(boolean del)
    {
        if (del)
        {
            if (caretPos < sb.length())
            {
                sb.deleteCharAt(caretPos);
            }
        }
        else
        {
            if (caretPos > 0)
            {
                sb.deleteCharAt(caretPos - 1);
                caretPos--;
            }
        }
    }
    
    /**
     * Inserts a digit into the current value at the caret position
     * @param num the digit to insert
     */
    private void digitEntered(String num)
    {
        if (sb.length() < maxLen)
        {
            sb.insert(caretPos, num);
            caretPos++;
        }
    }
    
    @Override
    public void mousePressed(int button, int mx, int my)
    {
        boolean consumed = false;
        if (button == 0)
        {
            if (mx > OK_BUTTON_X && mx < OK_BUTTON_X + OK_BUTTON_W && 
                    my > OK_BUTTON_Y && my < OK_BUTTON_Y + OK_BUTTON_H)
            {
                if (getDialogListener() != null)
                {
                    getDialogListener().actionPerformed(ACTION_OK_PRESSED);
                }
                consumed = true;
                return;
            }
            int xp = Math.round((getValue() * BAR_W) / (float)maxValue);
            xp = BAR_X + Math.min(xp, BAR_W);
            int distsq = (mx - xp) * (mx - xp) + (my - BAR_Y) * (my - BAR_Y);
            if (distsq <= SLIDER_R * SLIDER_R)
            {
                mouseDownX = mx;
                mouseDownY = my;
                sliderPos = xp;
                sliderDragged = true;
            }
        }
        if (!consumed)
        {
            super.mousePressed(button, mx, my);
        }
    }
    
    @Override
    public void mouseReleased(int button, int mx, int my)
    {
        if (button == 0)
        {
            if (sliderDragged)
            {
                int sp = (sliderPos + mx - mouseDownX) - BAR_X;
                sp = Math.max(0, Math.min(sp, BAR_W));
                int value = Math.round((sp * maxValue) / (float)BAR_W);
                sb.delete(0, sb.length());
                sb.append(value);
                caretPos = sb.length();
                sliderDragged = false;
            }
        }
    }
    

    @Override
    public void keyPressed(int keyCode, int keyChar)
    {
        switch (keyCode)
        {
        case Keyboard.KEY_LEFT:
            moveCaretLeft();
            break;
        case Keyboard.KEY_RIGHT:
            moveCaretRight();
            break;
        case Keyboard.KEY_DELETE:
            deletePressed(true);
            break;
        case Keyboard.KEY_BACK:
            deletePressed(false);
            break;
        case Keyboard.KEY_0:
        case Keyboard.KEY_1:
        case Keyboard.KEY_2:
        case Keyboard.KEY_3:
        case Keyboard.KEY_4:
        case Keyboard.KEY_5:
        case Keyboard.KEY_6:
        case Keyboard.KEY_7:
        case Keyboard.KEY_8:
        case Keyboard.KEY_9:
            digitEntered(Keyboard.getKeyName(keyCode));
            break;
        }
    }

    @Override
    public void keyReleased(int keyCode, int keyChar)
    {
        
    }
    
}
